import java.net.*;
import java.io.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.List;
import java.util.Collections;

public class CausalAtomicChannel extends BroadcastChannel{
    private ChatClientRecord owner;
    private AtomicChannel ac;
    private ApplicationListener app;
    private ArrayList<ChatMessage> prevDlvrs;
    private ArrayList<ChatMessage> causalDeps;

    public CausalAtomicChannel(ChatClientRecord rec, ApplicationListener l){
        owner = rec;
        app = l;
        prevDlvrs = new ArrayList<ChatMessage>();
        causalDeps = new ArrayList<ChatMessage>();
        ac = new AtomicChannel(rec, this);
    }

    public boolean addMember(ChatClientRecord member){
        return ac.addMember(member);
    }

    public boolean removeMember(ChatClientRecord member){
        return ac.removeMember(member);
    }

    public CopyOnWriteArrayList<ChatClientRecord> getMembers(){
        return ac.getMembers();
    }

    public boolean sendMessage(ChatMessage m){
        m.causalDependencies = causalDeps;
        causalDeps = new ArrayList<ChatMessage>();
        return ac.sendMessage(m);
    }

    public void receive(ChatMessage m){
        if(m.causalDependencies != null){
            Collections.sort((List<ChatMessage>)m.causalDependencies);
            for(ChatMessage mprime : m.causalDependencies){
                if(!prevDlvrs.contains(mprime)){
                    app.receive(mprime);
                    prevDlvrs.add(m);
                }
            }
            app.receive(m);
            prevDlvrs.add(m);
            if(!m.clientRec.equals(owner)){
                causalDeps.add(m);
            }
        }else{
            //System.err.println("Message had null causal dependencies!");
            app.receive(m);
            prevDlvrs.add(m);
            if(!m.clientRec.equals(owner)){
                causalDeps.add(m);
            }
        }
    }
}

